-- This is a lua script for use in Conky.
require 'cairo'
require 'cairo_xlib'
require 'rsvg'

function draw_svg_file(path,x,y,w,h)
    local rh = rsvg_handle_new_from_file(path)
    rect = RsvgRectangle:create()
    rect:set(x,y,w,h)
    rsvg_handle_render_document(rh,cr,rect)
    rsvg_destroy_handle(rh)
end

function draw_text(text,x,y,font,size,color,alpha,weight,align,maxwidth)
    slant = CAIRO_FONT_SLANT_NORMAL

    cairo_select_font_face (cr,font,slant,weight);
    cairo_set_font_size (cr, size)
    red, green, blue = hex2rgb(color)
    if alpha == nil then
        cairo_set_source_rgb (cr, red, green, blue)
    else
        cairo_set_source_rgba (cr,red, green, blue, alpha)
    end

    local extents = cairo_text_extents_t:create()
    tolua.takeownership(extents)
    cairo_text_extents(cr,text,extents)
    -- cut off text until it fits the maximum width
    if maxwidth then
        did=0
        maxwidth=tonumber(maxwidth)
        while extents.width > maxwidth do
            text=string.gsub(text, "[^\128-\191][\128-\191]*$", "") -- delete last char: stackoverflow.com/a/15980690
            cairo_text_extents(cr,text .. '…',extents)
            did=1
        end
    if did == 1 then text=text .. '…' end
    end

    if align == "right" or align == "center" then
        --~ print("Alignment: " .. align)
        --~ print("Text Extents Width: " .. extents.width)
        --~ print("Conky Window Width: " .. conky_window.width)
        if align == "right" then
            x = x - extents.width
        else
            x = x/2 - extents.width/2 + extents.x_bearing
        end
    end

    cairo_move_to (cr, x, y+size)
    cairo_show_text (cr, text)
    cairo_stroke (cr)
    return extents.width , extents.height
end

function hex2rgb(c)
    c=tonumber("0x"..c)
	return ((c / 0x10000) % 0x100) / 255, ((c / 0x100) % 0x100) / 255,
			(c % 0x100) / 255
end

function draw_line(x,y,length,height,color,alpha,cap)
    cairo_set_line_width(cr,height)
    cairo_set_line_cap(cr,cap)
    red, green, blue = hex2rgb(color)
    if alpha == nil then
        cairo_set_source_rgb (cr, red, green, blue)
    else
        cairo_set_source_rgba (cr,red, green, blue, alpha)
    end
    cairo_move_to(cr,x,y)
    cairo_rel_line_to (cr,length,0)
    cairo_stroke (cr)
end

function draw_box(x,y,w,h,color,alpha)
    --~ print("Drawing a box with color " .. color)
    red,green,blue=hex2rgb(color)
    if alpha == nil then
        cairo_set_source_rgb (cr, red, green, blue)
    else
        cairo_set_source_rgba (cr,red, green, blue, alpha)
    end
    cairo_rectangle (cr,x,y,w,h);
    cairo_fill (cr);
end

function conky_main(...)
    if conky_window == nil then
      return
    end

    update=tonumber(conky_parse ('${updates}'))
    -- This is necessary to avoid a conky/Xorg quirk that would run the script 4 times in a row before respecting its update interval.
    if update == 0 or update > 1 then
        -- this is the whole magic that "sources" the output of the above command, which was passed to lua through the conkyrc
        -- {...} is a table that contains a variable number of arguments passed to main(...)
        cmd = table.concat({...},' ')
        print("Update " .. update .. ", executing command: " .. cmd)
        cmd = io.popen(cmd)
        output = cmd:read('*a')
        io.close(cmd)
        --~ print("To be parsed:\n" .. output)
        parse = load(output) -- creates a function "parse()" to be executed 
        cmd=nil
        output=nil
    end
    cs = cairo_xlib_surface_create (conky_window.display,conky_window.drawable,conky_window.visual,conky_window.width,conky_window.height)
    cr = cairo_create (cs)

    --~ local fo = cairo_font_options_t:create()
    --~ tolua.takeownership(fo)

    --~ print(cairo_get_antialias(cr)) -- is this desired?
    --~ print(cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE)) -- is this desired?
    --~ print(cairo_font_options_set_antialias(cr, CAIRO_ANTIALIAS_NONE)) -- is this desired?
    --CAIRO_ANTIALIAS_DEFAULT --- Use the default antialiasing for the subsystem and target device, since 1.0
    --CAIRO_ANTIALIAS_NONE --- Use a bilevel alpha mask, since 1.0
    --CAIRO_ANTIALIAS_GRAY --- Perform single-color antialiasing (using shades of gray for black text on a white background, for example), since 1.0
    --CAIRO_ANTIALIAS_SUBPIXEL --- Perform antialiasing by taking advantage of the order of subpixel elements on devices such as LCD panels, since 1.0
    --CAIRO_ANTIALIAS_FAST --- Hint that the backend should perform some antialiasing but prefer speed over quality, since 1.12
    --CAIRO_ANTIALIAS_GOOD --- The backend should balance quality against performance, since 1.12
    --CAIRO_ANTIALIAS_BEST --- Hint that the backend should render at the highest quality, sacrificing speed if necessary, since 1.12

    parse()

    ----------------------------------------------------------
    ----------------------------------------------------------
    cairo_destroy (cr)
    cairo_surface_destroy (cs)
    cr = nil
    cs = nil
    collectgarbage();
end
